#include "placement_solver.h"
#include "sa_solver.h"
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
void Placement_Solver::LoadCube(const std::vector<Cube> & data) 
{
    data_ = data;
}

void Placement_Solver::LoadCube(const std::string &File_Name)
{
    std::ifstream fin(File_Name.c_str());
    assert(fin.is_open());
    unsigned size;
    fin >> size;
    assert(size > 0);
    data_.assign(size, Cube(0, 0, 0));

    for (unsigned i = 0; i < size; ++ i) {
        int n_length, n_width, n_height;
        fin >> n_length >> n_width >> n_height;
        assert(n_length > 0);
        assert(n_width  > 0);
        assert(n_height > 0);
        data_[i].length = n_length,
        data_[i].width = n_width,
        data_[i].height = n_height;
    }

    fin.close();
}

void Placement_Solver::LoadCube()
{
    unsigned size = 0;
    std::cin >> size;
    assert(size > 0);
    for (unsigned i = 0; i < size; ++ i) {
        int n_length, n_width, n_height;
        std::cin >> n_length >> n_width >> n_height;
        assert(n_length > 0);
        assert(n_width  > 0);
        assert(n_height > 0);
        data_[i].length = n_length,
        data_[i].width = n_width,
        data_[i].height = n_height;
    }
}

void Placement_Solver::Solve()
{
	std::cout << "Computing...." << std::endl;
	std::cout << "Wait Please..." << std::endl;
    SA_Solver solver(data_);
    solver.SetTimeLimitation(time_limitation_);
    solver.GetAns(data_);
    int minx = 1e9, maxx = 0, miny = 1e9, maxy = 0, minz = 1e9, maxz = 0;
    origin_total_volume_ = 0;
    for (int i = 0; i < data_.size(); i++) {
        minx = std::min(minx, data_[i].x); maxx = std::max(maxx, data_[i].x + data_[i].length);
        miny = std::min(miny, data_[i].y); maxy = std::max(maxy, data_[i].y + data_[i].width);
        minz = std::min(minz, data_[i].z); maxz = std::max(maxz, data_[i].z + data_[i].height);
        origin_total_volume_ += data_[i].length * data_[i].width * data_[i].height;
    }
    ansx_ = maxx - minx;
    ansy_ = maxy - miny;
    ansz_ = maxz - minz;
    bouding_volume_ = ansx_ * ansy_ * ansz_;
    return ;
}

void Placement_Solver::GetCube(std::vector<Cube> & data)
{
    data = data_;
    return ;
}

void Placement_Solver::Output(std::string File_Name /*= "Output.txt" */) {
    cout << "--------------Results--------------" << endl;
    cout << "There are " << data_.size() << " cubes in total." << endl;
    cout << "The total volume of cubes is " << origin_total_volume_ << "." << endl;
    cout << "The volume of bounding cube is " << bouding_volume_ << "." << endl;
    cout << "The fill ratio is " << (double) origin_total_volume_ / bouding_volume_ << "." << endl;
    cout << "The size of bounding cube is " << ansx_ << " X " << ansy_ << " X " << ansz_ << "." << endl;
    cout << "You can find the position information of packed cubes in \" " << File_Name << " \" ." << endl;
	std::ofstream fout(File_Name.c_str());
    fout << data_.size() << endl;
    for (int i = 0; i < data_.size(); i++) {
        fout << data_[i].length << ' ' << data_[i].width << ' ' << data_[i].height << ' ';
        fout << data_[i].x << ' ' << data_[i].y << ' ' << data_[i].z << endl;         
    }
    return ;
}